/***********************semaphore.h***************************** Semaphore类用于模拟信号量 用法如:Semaphore sem(1); (1)要求初始信号量值非负 (2)信号量P操作: sem.P(); (3)信号量V操作: sem.V(); ****************************************************/ #ifndef SEMAPHORE_H #define SEMAPHORE_H #include <windows.h> class Semaphore{ protected: HANDLE sem; public: //Semaphore(); //void SetValve(int SemValue); Semaphore(unsigned int SemValue); virtual ~Semaphore(); void P(); void V(); }; #endif
/*****************************semaphore.cpp************************************/ #include <windows.h> #include <LIMITS.H> #include <assert.h> #include "semaphore.h" Semaphore::Semaphore(unsigned int semValue){ if(semValue > LONG_MAX) semValue = LONG_MAX; sem = CreateSemaphore(NULL,semValue,LONG_MAX,NULL); } Semaphore::~Semaphore(){ CloseHandle(sem); } void Semaphore::P(){ DWORD dw = WaitForSingleObject(sem, INFINITE); assert(dw == WAIT_OBJECT_0); } void Semaphore::V(){ ReleaseSemaphore(sem,1,NULL); }
/*****************************thread.h************************************* 通过startThread开启线程 startThread(PTHREAD_START func,void * param); 用法: //定义一个PTHREAD_START类型的函数func unsigned int WINAPI func (void * param){ //... return 0; } //启动一个线程使其执行func函数 startThread(func,NULL); ********************************************************************/ #ifndef THREAD_H #define THREAD_H #include <windows.h> #include <process.h> /* from MSDN : Start address of a routine that begins execution of a new thread. For _beginthread, the calling convention is either __cdecl or __clrcall; for _beginthreadex, it is either __stdcall or __clrcall. WINAPI即为__stdcall */ typedef unsigned int (WINAPI *PTHREAD_START) (void *); /* chBEGINTHREADEX is From <Windows Via C & C++> */ #define chBEGINTHREADEX(psa, cbStackSize, pfnStartAddr, \ pvParam, dwCreateFlags, pdwThreadId) \ ((HANDLE)_beginthreadex( \ (void *) (psa), \ (unsigned) (cbStackSize), \ (PTHREAD_START) (pfnStartAddr), \ (void *) (pvParam), \ (unsigned) (dwCreateFlags), \ (unsigned *) (pdwThreadId))) // rename chBEGINTHREADEX to startThread for simplicity #define startThread(pfnStartAddr,pvParam)\ chBEGINTHREADEX(NULL, 0, (pfnStartAddr),(pvParam), 0, NULL) #endif
/*****************************main函数(主函数)************************************/ 假设偶数号哲学家先拿左边的筷子,右边的哲学家先拿起右边的筷子。 #include <windows.h> #include "semaphore.h" #include "thread.h" #include <iostream.h> #include <stdio.h> #define N 6 //哲学家的个数 #define LEFT(i) (i+N-1)%N //左边的筷子 #define RIGHT(i) (i==N-1)?0:(i+N)%N //右边的筷子 编号为N的哲学家的右边的筷子编号为0 /*******************************初始化信号量**************************************/ Semaphore ChopStick[N]={Semaphore(1),Semaphore(1),Semaphore(1),Semaphore(1),Semaphore(1),Semaphore(1)} ; /*******************************哲学家状态*******************************************/ void Eating(int Ph_Id) { printf("Philosopher%d: \tI'm eating......\t",(int)Ph_Id); } void Sleeping(int Ph_Id) { printf("Philosopher%d:\tI'm sleeping......\t",(int)Ph_Id); Sleep(rand()%10000); } void Thinking(int Ph_Id) { printf("Philosopher%d: \tI'm thinking......\t",(int)Ph_Id); } /********************************************************************/ void Philosopher(int pid){ while (true) { if (pid%2 == 0) //偶数号哲学家 { Thinking(pid); //等待中 ChopStick[LEFT(pid)].P(); //先拿起左边的筷子,再拿起右边的筷子 ChopStick[RIGHT(pid)].P(); Eating(pid); //获得的两个信号量则eating ChopStick[LEFT(pid)].V(); //先后释放左右信号量 ChopStick[RIGHT(pid)].V(); printf("\n"); } else if(pid%2==1 ) //奇数号哲学家 { Thinking(pid); ChopStick[RIGHT(pid)].P(); //先拿起右边的筷子,再拿起左边的筷子 ChopStick[LEFT(pid)].P(); Eating(pid); //左右都得到筷子后则eating ChopStick[RIGHT(pid)].V(); //先后释放右左信号量 ChopStick[LEFT(pid)].V(); printf("\n"); } Sleeping(pid); //吃完睡上一会儿 } } int main(){ HANDLE hPhilosopher[N]; //为每个哲学家分配一个线程 int count =0 ; for (int Philosopher_id =0 ;Philosopher_id<N;Philosopher_id++) //开启线程 { hPhilosopher[Philosopher_id] = startThread(Philosopher,Philosopher_id); if(count>5) break; } ::WaitForMultipleObjects(N,hPhilosopher,TRUE,INFINITE); for (Philosopher_id = 0 ; Philosopher_id<N;Philosopher_id++) { CloseHandle(hPhilosopher[Philosopher_id]); } return 0; }
You need to enable Javascript in your browser to edit pages.
help on how to format text
具体代码如下:
Table of Contents
/***********************semaphore.h***************************** Semaphore类用于模拟信号量 用法如:Semaphore sem(1); (1)要求初始信号量值非负 (2)信号量P操作: sem.P(); (3)信号量V操作: sem.V(); ****************************************************/ #ifndef SEMAPHORE_H #define SEMAPHORE_H #include <windows.h> class Semaphore{ protected: HANDLE sem; public: //Semaphore(); //void SetValve(int SemValue); Semaphore(unsigned int SemValue); virtual ~Semaphore(); void P(); void V(); }; #endif申明过后是定义文件:
/*****************************semaphore.cpp************************************/ #include <windows.h> #include <LIMITS.H> #include <assert.h> #include "semaphore.h" Semaphore::Semaphore(unsigned int semValue){ if(semValue > LONG_MAX) semValue = LONG_MAX; sem = CreateSemaphore(NULL,semValue,LONG_MAX,NULL); } Semaphore::~Semaphore(){ CloseHandle(sem); } void Semaphore::P(){ DWORD dw = WaitForSingleObject(sem, INFINITE); assert(dw == WAIT_OBJECT_0); } void Semaphore::V(){ ReleaseSemaphore(sem,1,NULL); }然后是线程头文件
/*****************************thread.h************************************* 通过startThread开启线程 startThread(PTHREAD_START func,void * param); 用法: //定义一个PTHREAD_START类型的函数func unsigned int WINAPI func (void * param){ //... return 0; } //启动一个线程使其执行func函数 startThread(func,NULL); ********************************************************************/ #ifndef THREAD_H #define THREAD_H #include <windows.h> #include <process.h> /* from MSDN : Start address of a routine that begins execution of a new thread. For _beginthread, the calling convention is either __cdecl or __clrcall; for _beginthreadex, it is either __stdcall or __clrcall. WINAPI即为__stdcall */ typedef unsigned int (WINAPI *PTHREAD_START) (void *); /* chBEGINTHREADEX is From <Windows Via C & C++> */ #define chBEGINTHREADEX(psa, cbStackSize, pfnStartAddr, \ pvParam, dwCreateFlags, pdwThreadId) \ ((HANDLE)_beginthreadex( \ (void *) (psa), \ (unsigned) (cbStackSize), \ (PTHREAD_START) (pfnStartAddr), \ (void *) (pvParam), \ (unsigned) (dwCreateFlags), \ (unsigned *) (pdwThreadId))) // rename chBEGINTHREADEX to startThread for simplicity #define startThread(pfnStartAddr,pvParam)\ chBEGINTHREADEX(NULL, 0, (pfnStartAddr),(pvParam), 0, NULL) #endif最后是驱动程序
/*****************************main函数(主函数)************************************/ 假设偶数号哲学家先拿左边的筷子,右边的哲学家先拿起右边的筷子。 #include <windows.h> #include "semaphore.h" #include "thread.h" #include <iostream.h> #include <stdio.h> #define N 6 //哲学家的个数 #define LEFT(i) (i+N-1)%N //左边的筷子 #define RIGHT(i) (i==N-1)?0:(i+N)%N //右边的筷子 编号为N的哲学家的右边的筷子编号为0 /*******************************初始化信号量**************************************/ Semaphore ChopStick[N]={Semaphore(1),Semaphore(1),Semaphore(1),Semaphore(1),Semaphore(1),Semaphore(1)} ; /*******************************哲学家状态*******************************************/ void Eating(int Ph_Id) { printf("Philosopher%d: \tI'm eating......\t",(int)Ph_Id); } void Sleeping(int Ph_Id) { printf("Philosopher%d:\tI'm sleeping......\t",(int)Ph_Id); Sleep(rand()%10000); } void Thinking(int Ph_Id) { printf("Philosopher%d: \tI'm thinking......\t",(int)Ph_Id); } /********************************************************************/ void Philosopher(int pid){ while (true) { if (pid%2 == 0) //偶数号哲学家 { Thinking(pid); //等待中 ChopStick[LEFT(pid)].P(); //先拿起左边的筷子,再拿起右边的筷子 ChopStick[RIGHT(pid)].P(); Eating(pid); //获得的两个信号量则eating ChopStick[LEFT(pid)].V(); //先后释放左右信号量 ChopStick[RIGHT(pid)].V(); printf("\n"); } else if(pid%2==1 ) //奇数号哲学家 { Thinking(pid); ChopStick[RIGHT(pid)].P(); //先拿起右边的筷子,再拿起左边的筷子 ChopStick[LEFT(pid)].P(); Eating(pid); //左右都得到筷子后则eating ChopStick[RIGHT(pid)].V(); //先后释放右左信号量 ChopStick[LEFT(pid)].V(); printf("\n"); } Sleeping(pid); //吃完睡上一会儿 } } int main(){ HANDLE hPhilosopher[N]; //为每个哲学家分配一个线程 int count =0 ; for (int Philosopher_id =0 ;Philosopher_id<N;Philosopher_id++) //开启线程 { hPhilosopher[Philosopher_id] = startThread(Philosopher,Philosopher_id); if(count>5) break; } ::WaitForMultipleObjects(N,hPhilosopher,TRUE,INFINITE); for (Philosopher_id = 0 ; Philosopher_id<N;Philosopher_id++) { CloseHandle(hPhilosopher[Philosopher_id]); } return 0; }